package com.shell.customer.esign.service.impl;

import com.shell.bee.base.utils.JsonUtil;
import com.shell.bee.base.utils.SpringContextUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.base.utils.SystemUtil.SystemMode;
import com.shell.bee.entity.mvc.RetMsg;
import com.shell.bee.esign.EsignConfiguration;
import com.shell.bee.esign.po.EsAcctAuth;
import com.shell.bee.esign.po.EsCust;
import com.shell.bee.esign.po.EsPayAuthRet;
import com.shell.bee.esign.service.EsAcctAuthService;
import com.shell.bee.esign.service.EsCustService;
import com.shell.bee.esign.service.EsPayAuthRetService;
import com.shell.bee.esign.service.EsignAuthService;
import com.shell.bee.esign.vo.BankAuthRequest;
import com.shell.bee.esign.vo.CodeValidRequest;
import com.shell.bee.esign.vo.EntInfoAuthRequest;
import com.shell.bee.esign.vo.EsignAuthResponse;
import com.shell.bee.esign.vo.EsignResponse;
import com.shell.bee.esign.vo.PayAuthRequest;
import com.shell.bee.esign.vo.TelecomAuthRequest;
import com.shell.bee.esign.vo.ToPayRequest;
import com.shell.bee.persistence.annotation.Pagination;
import com.shell.bee.persistence.model.PageLimit;
import com.shell.customer.accreditation.AccreditEvent;
import com.shell.customer.accreditation.rx.SetCusOptSubscriber;
import com.shell.customer.accreditation.rx.UpdateCusSubscriber;
import com.shell.customer.accreditation.vo.AccreditationVo;
import com.shell.customer.accreditation.vo.UserVo;
import com.shell.customer.base.service.CusAcctService;
import com.shell.customer.base.service.CusRecService;
import com.shell.customer.base.vo.CusAcctVo;
import com.shell.customer.cfca.service.CfcaAuthTxService;
import com.shell.customer.esign.service.EsignAuthTxService;
import com.shell.customer.po.CusAcct;
import com.shell.customer.po.CusOpt;
import com.shell.customer.po.CusRec;
import com.shell.customer.util.CustomerUtil;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.MessageSender;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import rx.Observable;

@Service
public class EsignAuthTxServiceImpl implements EsignAuthTxService {
	private Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private EsignAuthService esignAuthService;
	@Autowired
	private EsCustService esCustService;
	@Autowired
	private CusRecService cusRecService;
	@Autowired
	private CusAcctService cusAcctService;
	@Autowired
	private EsAcctAuthService esAcctAuthService;
	@Autowired
	private EsPayAuthRetService esPayAuthRetService;
	@Autowired
	private SetCusOptSubscriber setCusOptSubscriber;
	@Autowired
	private UpdateCusSubscriber updateCusSubscriber;
	@Autowired
	private CfcaAuthTxService cfcaAuthTxService;

	public EsignAuthResponse authBaseInfo(CusRec cus) throws Exception {
		if ("PERSONAL".equals(cus.getCusType())) {
			return null;
		}
		EntInfoAuthRequest request = new EntInfoAuthRequest();
		request.setName(cus.getCusName());
		if (StringUtil.emptyAndNull(cus.getSocCrCode())) {
			request.setCodeORG(cus.getOrgCode());
		} else {
			request.setCodeUSC(cus.getSocCrCode());
		}
		request.setLegalName(cus.getLrName());
		EsignAuthResponse response = this.esignAuthService.entInfoAuth(request);
		if (response.getErrCode() == 0) {
			saveEsCust(cus, response.getServiceId());
		}
		return response;
	}

	public EsignAuthResponse toPay(CusAcct cusAcct, String serviceId) throws Exception {
		String acctNo = cusAcct.getAcctNo();
		ToPayRequest request = new ToPayRequest();
		request.setServiceId(serviceId);
		request.setName(cusAcct.getAcctName());
		request.setBank(cusAcct.getBankName());
		request.setSubbranch(cusAcct.getBankDot());
		request.setCardno(cusAcct.getAcctNo());
		request.setProvice(cusAcct.getBankProvince());
		if (StringUtil.emptyAndNull(cusAcct.getBankCity())) {
			request.setCity(cusAcct.getBankProvince());
		} else {
			request.setCity(cusAcct.getBankCity());
		}
		request.setNotify(EsignConfiguration.getPayNotifyUrl());
		request.setPizId(acctNo);

		EsignAuthResponse response = this.esignAuthService.toPay(request);
		if (!SystemUtil.SystemMode.prod.equals(SystemUtil.getSystemMode())) {
			String payAmount = SpringContextUtil.getProperty("cust.acct.pay.amount");
			if (StringUtil.notEmpty(payAmount)) {
				response = new EsignAuthResponse();
				response.setErrCode(0);
			}
		}
		if (response.getErrCode() == 0) {
			EsAcctAuth acctAuth = (EsAcctAuth) this.esAcctAuthService.selectByKey(acctNo);
			if (acctAuth == null) {
				acctAuth = new EsAcctAuth();
				acctAuth.setAcctNo(acctNo);
				acctAuth.setCustId(cusAcct.getCusId());
			}
			acctAuth.setAuthState("1");
			acctAuth.setPayAuthNum(Integer.valueOf(0));
			acctAuth.setSerId(response.getServiceId());
			this.esAcctAuthService.saveOrUpdate(acctAuth);
		}
		return response;
	}

	public void saveEsCust(CusRec cus, String serviceId) {
		String custId = cus.getCusId();
		EsCust esCust = (EsCust) this.esCustService.selectByKey(custId);
		if (esCust == null) {
			esCust = new EsCust();
			esCust.setCustId(cus.getCusId());
			esCust.setCustNm(cus.getCusName());
			esCust.setSerId(serviceId);
			String authState;
			if ("PERSONAL".equals(cus.getCusType())) {
				authState = "0";
			} else {
				authState = "3";
			}
			esCust.setAuthState(authState);
			this.esCustService.save(esCust);
		} else {
			String cusName = cus.getCusName();
			if (!StringUtil.emptyAndNull(cusName)) {
				esCust.setCustNm(cusName);
			}
			esCust.setSerId(serviceId);
			this.esCustService.updateNotNull(esCust);
		}
	}

	public EsignResponse payAmountAuth(EsAcctAuth acctAuth, String serId, BigDecimal amount) throws Exception {
		PayAuthRequest request = new PayAuthRequest();
		request.setCash(String.valueOf(amount));
		request.setServiceId(serId);
		EsignResponse response = this.esignAuthService.payAuth(request);
		if (!SystemUtil.SystemMode.prod.equals(SystemUtil.getSystemMode())) {
			String payAmount = SpringContextUtil.getProperty("cust.acct.pay.amount");
			if (StringUtil.notEmpty(payAmount)) {
				response = new EsignResponse();
				if (amount.compareTo(new BigDecimal(payAmount)) == 0) {
					response.setErrCode(0);
				} else {
					response.setErrCode(1);
					response.setMsg("����������������");
				}
			}
		}
		if (response.getErrCode() == 0) {
			acctAuth.setAuthState("0");
		}
		acctAuth.setPayAuthNum(Integer.valueOf(acctAuth.getPayAuthNum().intValue() + 1));
		this.esAcctAuthService.updateNotNull(acctAuth);
		return response;
	}

	public RetMsg payAmountAuth(String acctNo, BigDecimal amount) {
		String custId = CommonDataUtil.getCurEntId();
		EsCust esCust = (EsCust) this.esCustService.selectByKey(custId);
		EsAcctAuth acctAuth = (EsAcctAuth) this.esAcctAuthService.selectByKey(acctNo);
		String msg = null;
		if ("0".equals(acctAuth.getAuthState())) {
			return new RetMsg("success", false, "��������������������������������");
		}
		try {
			if (acctAuth.getPayAuthNum().intValue() < 3) {
				EsignResponse response = payAmountAuth(acctAuth, esCust.getSerId(), amount);
				if (response.getErrCode() != 0) {
					msg = response.getMsg();
				}
			} else {
				return reAuth(custId, acctNo);
			}
		} catch (Exception e) {
			e.printStackTrace();
			msg = "��������������" + e.getMessage();
		}
		if (msg != null) {
			return new RetMsg("error", false, msg);
		}
		if (!"0".equals(esCust.getAuthState())) {
			esCust.setAuthState("0");
			this.esCustService.updateNotNull(esCust);
		}
		return new RetMsg("success", true, "������������");
	}

	public RetMsg reAuth(String custId, String acctNo) throws Exception {
		CusRec cus = (CusRec) this.cusRecService.selectByKey(custId);
		CusAcct acct = this.cusAcctService.selectByAcctNo(custId, acctNo);
		EsignAuthResponse response = authBaseInfo(cus);
		if (response.getErrCode() == 0) {
			response = toPay(acct, response.getServiceId());
			if (response.getErrCode() != 0) {
				return new RetMsg("error", true, "����������������3��������������������");
			}
		} else {
			return new RetMsg("error", true, "����������������3����������������������������");
		}
		return new RetMsg("error", true, "����������������3��������������������������������������������������");
	}

	public RetMsg personBankAuth(String cardNo, String name, String mobile, String idno) {
		BankAuthRequest request = new BankAuthRequest();
		request.setCardno(cardNo);
		request.setName(name);
		request.setMobile(mobile);
		request.setIdno(idno);
		EsignAuthResponse response = null;
		try {
			response = this.esignAuthService.bankAuth(request);
			if (response.getErrCode() != 0) {
				return new RetMsg("error", true, "��������������" + response.getMsg());
			}
		} catch (Exception e) {
			return new RetMsg("error", true, "��������������" + e.getMessage());
		}
		EsCust cust = (EsCust) this.esCustService.selectByKey(CommonDataUtil.getUserId());
		if (cust == null) {
			cust = new EsCust();
			cust.setCustId(CommonDataUtil.getUserId());
			cust.setCustNm(name);
			cust.setMobile(mobile);
			cust.setAuthState("2");
		}
		cust.setSerId(response.getServiceId());
		this.esCustService.saveOrUpdate(cust);
		EsAcctAuth acctAuth = new EsAcctAuth();
		acctAuth.setAcctNo(cardNo);
		acctAuth.setAuthState("0");
		return new RetMsg("success", false, "������������������������������");
	}

	public RetMsg personCodeValid(String custId, String code) {
		EsCust cust = (EsCust) this.esCustService.selectByKey(custId);
		CodeValidRequest request = new CodeValidRequest();
		request.setCode(code);
		request.setServiceId(cust.getSerId());
		EsignAuthResponse response = null;
		try {
			response = this.esignAuthService.codeValid(request);
			if (response.getErrCode() != 0) {
				return new RetMsg("error", true, "��������������������" + response.getMsg());
			}
		} catch (Exception e) {
			e.printStackTrace();
			return new RetMsg("error", true, "��������������������" + e.getMessage());
		}
		cust.setAuthState("0");
		this.esCustService.updateNotNull(cust);
		return new RetMsg("success", false, "������������������");
	}

	public void payNotify(String esignReturn) {
		this.logger.info("������������������" + esignReturn);
		try {
			if (!StringUtil.emptyAndNull(esignReturn)) {
				Map<String, String> ret = (Map) JsonUtil.fromJson(esignReturn, Map.class);
				String result = (String) ret.get("result");
				String pizId = (String) ret.get("pizId");
				if (!StringUtil.emptyAndNull(pizId)) {
					EsAcctAuth acctAuth = (EsAcctAuth) this.esAcctAuthService.selectByKey(pizId);
					EsPayAuthRet authRet = new EsPayAuthRet();
					authRet.setRetId(SystemUtil.getUUID());
					authRet.setAcctNo(acctAuth.getAcctNo());
					authRet.setResult(result);
					authRet.setPizId(pizId);
					authRet.setMsg((String) ret.get("msg"));
					authRet.setPayedTime((String) ret.get("payedTime"));
					authRet.setSerId((String) ret.get("serviceId"));
					this.esPayAuthRetService.save(authRet);
					if (!"0".equals(acctAuth.getAuthState())) {
						String messageTemplate;
						if (("SUCCESS".equals(result)) && (StringUtil.notEmpty(authRet.getMsg()))
								&& (("S0001|��������".equals(authRet.getMsg()))
										|| (authRet.getMsg().contains("SUCCESS")))) {
							acctAuth.setAuthState("3");
							messageTemplate = "MT07001";
						} else {
							acctAuth.setAuthState("2");
							messageTemplate = "MT07002";
						}
						MessageSender.sendMessageByTmpl("-1", messageTemplate, null, acctAuth

								.getCustId());
						this.esAcctAuthService.updateNotNull(acctAuth);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			this.logger.error("��������������������", e);
		}
	}

	public EsignAuthResponse personTelecomAuth(UserVo user) throws Exception {
		TelecomAuthRequest request = new TelecomAuthRequest();
		request.setName(user.getUserName());
		request.setIdno(user.getCertNo());
		request.setMobile(user.getPhoneNo());
		EsignAuthResponse response = this.esignAuthService.telecomAuth(request);
		if (!SystemUtil.SystemMode.prod.equals(SystemUtil.getSystemMode())) {
			response = new EsignAuthResponse();
			response.setErrCode(0);
		}
		if (response.getErrCode() == 0) {
			EsCust esCust = (EsCust) this.esCustService.selectByKey(user.getUserId());
			if (esCust == null) {
				esCust = new EsCust();
				esCust.setCustId(user.getUserId());
			}
			esCust.setCustNm(user.getUserName());
			esCust.setMobile(user.getPhoneNo());
			esCust.setSerId(response.getServiceId());
			esCust.setAuthState("0");
			this.esCustService.saveOrUpdate(esCust);
		}
		return response;
	}

	@Pagination
	public List<CusAcctVo> selectEsignAcctAuthList(PageLimit limit, String custId) {
		return this.cusAcctService.selectEsignAcctAuthList(custId);
	}

	public EsAcctAuth getAcctAuth(String cusId, String acctNo) {
		EsAcctAuth acctAuth = new EsAcctAuth();
		acctAuth.setCustId(cusId);
		acctAuth.setAcctNo(acctNo);
		return (EsAcctAuth) this.esAcctAuthService.selectOne(acctAuth);
	}

	public RetMsg payAmountAuthForAddCus(String acctNo, BigDecimal amount) {
		String custId = CommonDataUtil.getCurEntId();
		RetMsg msg = new RetMsg("success", false, "������������");
		if (CustomerUtil.onEsign()) {
			msg = payAmountAuth(acctNo, amount);
		}
		if (!"error".equals(msg.getType())) {
			CusRec cus = (CusRec) this.cusRecService.selectByKey(custId);

			AccreditationVo accreditationVo = new AccreditationVo();
			accreditationVo.setCustomerC(cus);
			CusOpt cusOpt = new CusOpt();
			cusOpt.setCusState("E");
			cusOpt.setNextState("");
			cusOpt.setBizCode("3");
			cusOpt.setCurState(cus.getCusState());

			AccreditEvent accreditEvent = new AccreditEvent();
			accreditEvent.setAccreditationVo(accreditationVo);
			accreditEvent.setCusOpt(cusOpt);

			Observable<AccreditEvent> observers = Observable.just(accreditEvent);

			observers.subscribe(this.setCusOptSubscriber);
			observers.subscribe(this.updateCusSubscriber);
		}
		return msg;
	}

	public RetMsg toPayForAddCus(String acctNo) throws Exception {
		String custId = CommonDataUtil.getCurEntId();
		CusRec cus = (CusRec) this.cusRecService.selectByKey(custId);
		CusAcct acct = this.cusAcctService.selectByAcctNo(custId, acctNo);
		if (acct == null) {
			return new RetMsg("error", true, "������������");
		}
		if (CustomerUtil.onEsign()) {
			EsignAuthResponse response = authBaseInfo(cus);
			if ((response != null) && (response.getErrCode() == 0)) {
				response = toPay(acct, response.getServiceId());
				if (response.getErrCode() != 0) {
					return new RetMsg("error", true, "��������������e������" + response.getMsg());
				}
			} else {
				return new RetMsg("error", true, "��������������e������" + response.getMsg());
			}
		}
		return new RetMsg("success", false, "��������������");
	}
}
